﻿namespace Neovolve.Extensibility.ReSharper
{
    using System;
    using JetBrains.ReSharper.Daemon;
    using JetBrains.ReSharper.Psi;
    using JetBrains.ReSharper.Psi.CSharp;
    using JetBrains.ReSharper.Psi.CSharp.Tree;

    /// <summary>
    /// The <see cref="ConvertTypeStageProcess"/>
    ///   class is used to process a file looking for types to be converted.
    /// </summary>
    internal class ConvertTypeStageProcess : IDaemonStageProcess
    {
        /// <summary>
        /// Stores the process for the stage.
        /// </summary>
        private readonly IDaemonProcess _process;

        /// <summary>
        /// Initializes a new instance of the <see cref="ConvertTypeStageProcess"/> class.
        /// </summary>
        /// <param name="process">
        /// The process.
        /// </param>
        public ConvertTypeStageProcess(IDaemonProcess process)
        {
            _process = process;
        }

        /// <summary>
        /// Executes the specified committer.
        /// </summary>
        /// <param name="committer">
        /// The committer.
        /// </param>
        public void Execute(Action<DaemonStageResult> committer)
        {
            if (committer == null)
            {
                throw new ArgumentNullException("committer");
            }

            if (_process.InterruptFlag)
            {
                return;
            }

            // Retrieve the project file
            // (using the daemon we stored in the constructor)
            ICSharpFile file = PsiManager.GetInstance(_process.Solution).GetPsiFile(_process.ProjectFile, CSharpLanguageService.CSHARP) as ICSharpFile;

            if (file == null)
            {
                return;
            }

            ConvertTypeRecursiveElementProcessor processor = new ConvertTypeRecursiveElementProcessor(_process);

            // Run the AST tree processing - at some point it will come 
            // to our IRecursiveElementProcessor implementation
            file.ProcessDescendants(processor);

            DaemonStageResult result = new DaemonStageResult(processor.Highlightings);

            // The last thing we should do is notify the daemon
            committer(result);
        }
    }
}